#include "BackpropagationNetwork.h"

using namespace NeuralPlusPlus::Core::Backpropagation;
using namespace NeuralPlusPlus::Core;

NeuralPlusPlus::Core::Backpropagation::BackpropagationNetwork::BackpropagationNetwork( ActivationLayer *inputLayer, ActivationLayer *outputLayer ) : Network(inputLayer, outputLayer, TrainingMethodType::Supervised)
	{
	this->meanSquaredError = 0;
	this->isValidMSE = false;
	}

void NeuralPlusPlus::Core::Backpropagation::BackpropagationNetwork::Learn( TrainingSample *trainingSample, int currentIteration, int trainingEpochs )
	{
	meanSquaredError = 0;
	isValidMSE = true;
	__super::Learn(trainingSample, currentIteration, trainingEpochs);
	}

void NeuralPlusPlus::Core::Backpropagation::BackpropagationNetwork::Learn( TrainingSet *trainingSet, int trainingEpochs )
	{
	__super::Learn(trainingSet, trainingEpochs);
	}
void NeuralPlusPlus::Core::Backpropagation::BackpropagationNetwork::OnBeginEpoch( int currentIteration, TrainingSet *trainingSet )
	{
	meanSquaredError = 0;
	isValidMSE = false;
	__super::OnBeginEpoch(currentIteration, trainingSet);
	}

void NeuralPlusPlus::Core::Backpropagation::BackpropagationNetwork::OnEndEpoch( int currentIteration, TrainingSet *trainingSet )
	{
	meanSquaredError /= trainingSet->TrainingSamples.size();
	isValidMSE = true;
	__super::OnEndEpoch(currentIteration, trainingSet);
	}

void NeuralPlusPlus::Core::Backpropagation::BackpropagationNetwork::LearnSample( TrainingSample *trainingSample, int currentIteration, int trainingEpochs )
	{
	int layerCount = layers.size();

	inputLayer->SetInput(trainingSample->InputVector);

	for(int i=0;i<layerCount;i++)
		{
		layers[i]->Run();
		}
	ActivationLayer *outputLayer = (ActivationLayer*)this->outputLayer;
	meanSquaredError += outputLayer->SetErrors(trainingSample->OutputVector);

	for(int i=layerCount-1;i>=0;i--)
		{
		ActivationLayer *layer = (ActivationLayer*)layers[i];
		if (layer != NULL)
			{
			layer->EvaluateErrors();
			}
		}

	for(int i=0;i<layerCount;i++)
		{
		layers[i]->Learn(currentIteration, trainingEpochs);
		}
	}